package com.xmindguoguo.boot.core.shiro;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import com.xmindguoguo.boot.common.constant.GlobalConstant;
import com.xmindguoguo.boot.common.constant.SessionConstant;
import com.xmindguoguo.boot.core.shiro.factroy.IShiro;
import com.xmindguoguo.boot.core.shiro.factroy.ShiroFactroy;
import com.xmindguoguo.boot.modular.system.model.TSystemUserModel;

/**
 * 自定义验证
 * 
 * @ClassName ShiroDbRealm
 * @author <a href="892042158@qq.com" target="_blank">于国帅</a>
 * @date 2018年12月23日 下午2:57:02
 *
 */
public class ShiroDbRealm extends AuthorizingRealm {

    /**
     * 登录认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        IShiro shiroFactory = ShiroFactroy.me();
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        TSystemUserModel user = shiroFactory.user(token.getUsername());
        ShiroUser shiroUser = shiroFactory.shiroUser(user);
        SimpleAuthenticationInfo info = shiroFactory.info(shiroUser, user, super.getName());
        return info;
    }

    /**
     * 权限认证
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        IShiro shiroFactory = ShiroFactroy.me();
        ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
        List<Long> roleList = shiroUser.getRoleList();
        Set<String> permissionSet = new HashSet<>();
        Set<String> roleNameSet = new HashSet<>();
        // 这里增加超级管理隐藏角色 ，太可怕了竟然莫名出现了问题也不知道谁整的
        if (shiroUser.getId() == GlobalConstant.Const.ADMIN_ID) {
            // 那么增加所有的权限URL 和所有的角色
            Set<String> loginAndPermissionSet = shiroFactory.findLoginAndPermissionSet();
            permissionSet.addAll(loginAndPermissionSet);
            Set<String> roleNameALLSet = shiroFactory.findRoleNameSet();
            roleNameSet.addAll(roleNameALLSet);
        } else if (CollectionUtils.isNotEmpty(roleList)) {
            for (Long roleId : roleList) { // 根据角色放入权限id
                List<String> permissions = shiroFactory.findPermissionsByRoleId(roleId);
                if (permissions != null) {
                    for (String permission : permissions) {
                        if (StringUtils.isNotEmpty(permission)) {
                            permissionSet.add(permission);
                        }
                    }
                }
                String roleName = shiroFactory.findRoleNameByRoleId(roleId);
                roleNameSet.add(roleName);
            }
        }
        // 这里增加需要登录 不需要权限的集合
        Set<String> loginNoPermissionSet = shiroFactory.findLoginNoPermissionSet();
        permissionSet.addAll(loginNoPermissionSet);
        ShiroKit.setSessionAttr(SessionConstant.Permission.PERMISSIONS, StringUtils.join(permissionSet, ","));
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermissions(permissionSet);
        info.addRoles(roleNameSet);
        return info;
    }

    /**
     * 设置认证加密方式
     */
    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        HashedCredentialsMatcher md5CredentialsMatcher = new HashedCredentialsMatcher();
        md5CredentialsMatcher.setHashAlgorithmName(ShiroKit.hashAlgorithmName);
        md5CredentialsMatcher.setHashIterations(ShiroKit.hashIterations);
        super.setCredentialsMatcher(md5CredentialsMatcher);
    }
}
